${gen.setFilepath(settings.javaPath + "/com.example.utils")}
${gen.setFilename("MyBatisUtils.java")}
package com.example.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.CaseFormat;
import org.apache.ibatis.reflection.property.PropertyNamer;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页排序参数处理
 */
public class MyBatisUtils {
    /**
     * 把 spring-data-commons 的 Pageable 分页对象转换成 Mybatis-Plus 的 Page 对象
     *
     * @param pageable 分页参数
     * @param <T>      实体对象
     * @return MyBatis-Plus 的分页对象
     */
    public static <T> Page<T> toPage(Pageable pageable) {
        return toPage(pageable, true);
    }

    /**
     * 把 spring-data-commons 的 Pageable 分页对象转换成 Mybatis-Plus 的 Page 对象
     *
     * @param <T>          实体对象
     * @param pageable     分页参数
     * @param handlerOrder 是否处理排序信息
     * @return MyBatis -Plus 的分页对象
     */
    public static <T> Page<T> toPage(Pageable pageable, boolean handlerOrder) {
        Page<T> page = new Page<>(pageable.getPageNumber(), pageable.getPageSize());
        if (handlerOrder) {
            Sort orders = pageable.getSort();
            for (Sort.Order order : orders) {
                // 把驼峰命名规则转换为下划线
                String property = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order.getProperty());
                switch (order.getDirection()) {
                    case ASC:
                        page.addOrder(OrderItem.asc(property));
                        break;
                    case DESC:
                        page.addOrder(OrderItem.desc(property));
                        break;
                    default:
                }
            }
        }
        return page;
    }

    /**
     * 在 LambdaQueryChainWrapper 对象中添加一个排序字段。
     * 添加条件： function 为实体类的 get 方法，其 get 方法对应的 field 需要与 order.getProperty() 保持一致才会添加排序字段
     *
     * @param <T>               实体对象
     * @param lambdaQuery       MyBatis-Plus 的 LambdaQuery 对象
     * @param pageable          spring-data-commons 的 Pageable 分页查询对象
     * @param entityOrderFields 实体对象 T 对应的可被排序的 get 字段方法
     * @see #lambdaQueryAddOrder(LambdaQueryChainWrapper, Order, SFunction) 说明详情
     */
    public static <T> void lambdaQueryAddOrder(LambdaQueryChainWrapper<T> lambdaQuery, Pageable pageable, List<SFunction<T, ?>> entityOrderFields) {
        pageable.getSort().stream().forEach(order -> {
            for (SFunction<T, ?> field : entityOrderFields) {
                if (lambdaQueryAddOrder(lambdaQuery, order, field)) {
                    break;
                }
            }
        });
    }

    /**
     * 在 LambdaQueryChainWrapper 对象中添加一个排序字段。
     * 添加条件： function 为实体类的 get 方法，其 get 方法对应的 field 需要与 order.getProperty() 保持一致才会添加排序字段
     *
     * @param <T>         实体对象
     * @param lambdaQuery MyBatis-Plus 的 LambdaQuery 对象
     * @param order       spring-data-commons Pageable 分页查询对象中的排序对象
     * @param function    实体对象 T 对应的可被排序的 get 字段方法
     * @return the boolean
     */
    public static <T> boolean lambdaQueryAddOrder(LambdaQueryChainWrapper<T> lambdaQuery, Order order, SFunction<T, ?> function) {
        String field = PropertyNamer.methodToProperty(LambdaUtils.resolve(function).getImplMethodName());
        if (order.getProperty().equals(field)) {
            if (Sort.Direction.ASC.equals(order.getDirection())) {
                lambdaQuery.orderByAsc(function);
            } else {
                lambdaQuery.orderByDesc(function);
            }
            return true;
        }
        return false;
    }

    /**
     * 组合排序参数信息
     *
     * @param wrapper 查询对象
     * @param sorts   排序信息：["field1,asc","field2,desc"]
     */
    @Deprecated
    public static void handlerSorts(QueryWrapper<?> wrapper, String[] sorts) {
        handlerSorts(sorts, wrapper::orderByAsc, wrapper::orderByDesc);
    }

    /**
     * 组合排序参数信息
     *
     * @param page  分页对象
     * @param sorts 排序信息：["field1,asc","field2,desc"]
     */
    @Deprecated
    public static void handlerSorts(Page<?> page, String[] sorts) {
        handlerSorts(sorts, (fieldName) -> {
            page.addOrder(OrderItem.asc(fieldName));
        }, (fieldName) -> {
            page.addOrder(OrderItem.desc(fieldName));
        });
    }

    /**
     * 把查询到的分页对象转换成map信息（同时把Entity转换成DTO对象）
     *
     * @param page              分页对象
     * @param streamMapFunction Entity to DTO 方法
     * @param <T>               Entity 对象
     * @param <R>               Dto 对象
     * @return 分页结果的map形式信息
     * @deprecated 请使用 MyBatis-Plus 提供的 R 对象，可在 Controller 中继承 ApiController 来提供便捷的返回操作
     */
    @Deprecated
    public static <T, R> Map<String, Object> pageToMap(Page<T> page, Function<? super T, ? extends R> streamMapFunction) {
        return pageToMap(page, "data", streamMapFunction);
    }

    /**
     * 把查询到的分页对象转换成map信息（同时把Entity转换成DTO对象）
     *
     * @param page              分页对象
     * @param dataFieldName     数据对象的字段名称
     * @param streamMapFunction Entity to DTO 方法
     * @param <T>               Entity 对象
     * @param <R>               Dto 对象
     * @return 分页结果的map形式信息
     * @deprecated 请使用 MyBatis-Plus 提供的 R 对象，可在 Controller 中继承 ApiController 来提供便捷的返回操作
     */
    @Deprecated
    public static <T, R> Map<String, Object> pageToMap(Page<T> page, String dataFieldName, Function<? super T, ? extends R> streamMapFunction) {
        List<R> collect = page.getRecords()
                .stream()
                .map(streamMapFunction)
                .collect(Collectors.toList());

        Map<String, Object> map = new LinkedHashMap<>();
        Map<String, Object> pageMap = new LinkedHashMap<>();
        pageMap.put("page", page.getCurrent());
        pageMap.put("size", page.getSize());
        pageMap.put("total", page.getTotal());
        pageMap.put("pages", page.getPages());
        pageMap.put("orders", page.getOrders());
        map.put(dataFieldName, collect);
        map.put("page", pageMap);
        return map;
    }

    /**
     * 处理分页排序信息
     *
     * @param sorts   排序信息
     * @param ascRun  正序执行方法
     * @param descRun 倒序执行方法
     */
    @Deprecated
    private static void handlerSorts(String[] sorts, Consumer<String> ascRun, Consumer<String> descRun) {
        if (sorts == null) {
            return;
        }
        for (String sort : sorts) {
            String[] split = sort.split(",");
            if (split[0] == null) {
                continue;
            }
            String fieldName = split[0].trim();
            run(split[1], () -> {
                ascRun.accept(fieldName);
            }, () -> {
                descRun.accept(fieldName);
            });
        }
    }

    /**
     * 根据排序值类型判断是正序还是倒序
     *
     * @param sortType 排序值类型：asc、desc
     * @param ascRun   正序执行方法
     * @param descRun  倒序执行方法
     */
    @Deprecated
    private static void run(String sortType, Runnable ascRun, Runnable descRun) {
        if (sortType == null) {
            ascRun.run();
            return;
        }
        sortType = sortType.trim().toUpperCase();
        final String desc = "DESC";
        if (desc.equals(sortType)) {
            descRun.run();
        } else {
            ascRun.run();
        }
    }
}
